Question: I want to read a
BLOB into my PL/SQL but I don't understand how to modify the select statement to
accept a large result value. Is there a general stored procedure for
reading a BLOB in Oracle?
Answer: Oracle supports over 20
data types, and you can even define your own custom data types. For large
objects, Oracle offers the BLOB,
CLOB
and LONG RAW (obsolete).
There are several documented methods to
unload blob from the database, mostly using PL/SQL with utl_file.put_raw
(see MOSC note 330146.1) and with
java with FileOutputStream (see MOSC
note 247546.1) .
The following SQL*Plus script will run on
UNIX/Linux and select a blob, using xxd to translate the blob output.
Remember, the blob could be a photograph, an audio file or a video:
sqlplus -s scott/tiger <<EOF |xxd -p -r > doc.pdf
set pages 0 lin 17000 long 1000000000 longc 16384
select document from
emp where ename=user;
EOF
Note: When defining a BLOB column, the LOB storage clause is not
needed if the maximum size of the BLOB doesn't exceed 4,000 bytes. Up
to 4,000 bytes can be stored in-line with the other data in the
tablespace. If the length of the BLOB exceeds 4000 bytes it must be
stored in either a system defaulted storage (the same as the default
for the table it resides in) or in an explicitly defined LOB
storage area.
Here are the details for defining, reading and writing BLOB
columns:
Dr. Hall demonstrates the procedure for reading BLOB data types
in his book "Oracle
PL/SQL Tuning: Expert Secrets for High Performance Programming". Here
is a sample from Dr. Hall, reading a BLOB with PL/SQL:
CREATE OR REPLACE
PROCEDURE extract_file(product_id in number) IS
vblob BLOB;
vstart NUMBER := 1;
bytelen NUMBER := 32000;
len NUMBER;
my_vr RAW(32000);
x NUMBER;
l_output utl_file.file_type;
BEGIN
-- define output directory
l_output := utl_file.fopen('DIR_TEMP', 'filename','wb', 32760);
vstart := 1;
bytelen := 32000;
-- get length of blob
SELECT dbms_lob.getlength(productblob)
INTO len
FROM products
WHERE id = product_id;
-- save blob length
x := len;
-- select blob into variable
SELECT product_blob
INTO vblob
FROM products
WHERE id = product_id;
-- if small enough for a single write
IF len < 32760 THEN
utl_file.put_raw(l_output,vblob);
utl_file.fflush(l_output);
ELSE -- write in pieces
vstart := 1;
WHILE vstart < len and bytelen > 0
LOOP
dbms_lob.read(vblob,bytelen,vstart,my_vr);
utl_file.put_raw(l_output,my_vr);
utl_file.fflush(l_output);
-- set the start position for the next cut
vstart := vstart + bytelen;
-- set the end position if less than 32000 bytes
x := x - bytelen;
IF x < 32000 THEN
bytelen := x;
END IF;
END IF;
utl_file.fclose(l_output);
end loop;
Also see these notes on reading and writing BLOBs: